//懒汉模式-第一次使用实例对象时，创建对象
#include<iostream>
#include<mutex>
#include<thread>

using namespace std;
class Singleton1
{
public:
	//这里一定要使用双重检查锁定（double check）的方式加锁，才能保证效率和安全
	static Singleton1* GetInstance()
	{
		//通过两次检查，只有在对象未初始化时才需要获取锁，这样可以减少锁的获取次数，提高性能。
		if (nullptr == m_pInstance) //线程首先检查一个对象是否已经被初始化
		{
			m_mtx.lock();
			if (nullptr == m_pInstance) //再次确认对象是否已经初始化
			{
				m_pInstance = new Singleton1();
			}
			m_mtx.unlock();
		}
		return m_pInstance;
	}

	//实现一个内嵌垃圾回收类
	class CGarbo
	{
	public:
		~CGarbo()
		{
			if (Singleton1::m_pInstance)
			{
				delete Singleton1::m_pInstance;
			}
		}
	};
	//定义的静态成员变量，程序结束时，系统会自动调用他的析构函数去释放单例对象
	static CGarbo Garbo;

private:
	Singleton1() {};//构造函数私有

	//防止拷贝
	Singleton1(Singleton1 const&) = delete;
	Singleton1& operator =(Singleton1 const&) = delete;
private:
	static Singleton1* m_pInstance;//单例对象指针
	static mutex m_mtx;
};

//单例模式-一个类只能创建一个对象
//饿汉模式-程序启动时就创建唯一的实例对象

class Singleton
{
public:
	static Singleton* GetInstance()
	{
		return &m_instance;
	}
private:
	Singleton() {};//构造函数私有

	//防止拷贝
	Singleton(Singleton const&) = delete;
	Singleton& operator =(Singleton const&) = delete;
private:
	static Singleton m_instance;
};

Singleton Singleton::m_instance;//在程序入口之前就完成对单例对象的初始化

